package com.atguigu.juc.day03.scene;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class Demo05ForkJoin {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 1、创建 ForkJoinPool
        ForkJoinPool forkJoinPool = new ForkJoinPool();

        // 2、创建指定的任务
        MyForkJoinTask myForkJoinTask = new MyForkJoinTask(1, 99);

        // 3、把我们的任务提交到 ForkJoinPool
        forkJoinPool.submit(myForkJoinTask);

        // 4、获取最终计算结果
        Object computeResult = myForkJoinTask.get();
        System.out.println("computeResult = " + computeResult);

    }

}

class MyForkJoinTask extends RecursiveTask {

    private int begin;
    private int end;

    public MyForkJoinTask(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    public static final int ADJUST_VALUE = 10;

    private int result;

    @Override
    protected Object compute() {

        // 1、检查当前任务区间是否在最小颗粒度范围内
        if (end - begin <= ADJUST_VALUE) {

            // 2、如果在范围内，则执行累加
            for (int i = begin; i <= end; i++) {
                result = result + i;
            }
        } else {

            // 3、如果不在，则执行拆分
            int leftBegin = begin;

            // leftEnd = (end - begin) / 2 + begin
            // leftEnd = (end - begin) / 2 + 2 * begin / 2
            // leftEnd = (end - begin + 2 * begin) / 2
            // leftEnd = (end + begin) / 2
            int leftEnd = (end + begin) / 2;
            int rightBegin = leftEnd + 1;
            int rightEnd = end;

            // 4、根据拆分得到的任务区间创建子任务
            MyForkJoinTask leftTask = new MyForkJoinTask(leftBegin, leftEnd);
            MyForkJoinTask rightTask = new MyForkJoinTask(rightBegin, rightEnd);

            ForkJoinTask forkLeft = leftTask.fork();
            ForkJoinTask forkRight = rightTask.fork();

            // 5、获取子任务的计算结果
            int leftResult = (int) forkLeft.join();
            int rightResult = (int) forkRight.join();

            // 6、合并左右两边的计算结果
            result = leftResult + rightResult;
        }

        return result;
    }
}